package com.example.demo.aspect;

import com.example.demo.common.ThreadUserPojo;
import com.example.demo.common.TokenPojo;
import com.example.demo.decorator.Authorize;
import com.example.demo.exception.BusinessException;
import com.example.demo.service.baseContext.BaseContextService;
import com.example.demo.service.cache.CacheTokenService;
import com.example.demo.utils.RequestUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Objects;

@Aspect
@Component
public class PermissionAspect {
    @Autowired
    private CacheTokenService cacheTokenService;
    @Autowired
    private BaseContextService bcs;

    @Around("@annotation(authorize)")
    public Object around(ProceedingJoinPoint joinPoint, Authorize authorize) throws Throwable {
        // 这里写鉴权逻辑
        String permission = authorize.permission();
        String label = authorize.label();
        boolean ifIgnore = authorize.ifIgnore();
        boolean ifIgnoreButResolveToken = authorize.ifIgnoreButResolveToken();
        boolean ifIgnoreParamInLog = authorize.ifIgnoreParamInLog();

        boolean tokenUsable = true;
        HttpServletRequest request = getCurrentRequest();

        String oauth = request.getHeader("authorization");
        String token = RequestUtils.getTokenUuidFromAuth(oauth);
        try {
            TokenPojo decoded = cacheTokenService.verifyToken(token);
            if (decoded != null) {
                bcs.setUserData(new ThreadUserPojo(decoded.getUserId(), token, decoded.getLoginRole(), permission));
            } else {
                tokenUsable = false;
            }
        } catch (Exception e) {
            tokenUsable = false;
        }

        if (!tokenUsable && !ifIgnore) {
            throw new BusinessException("Unauthorized.", 401);
        }
        return joinPoint.proceed();
    }

    private HttpServletRequest getCurrentRequest() {
        try {
            return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        } catch (Exception e) {
            return null;
        }
    }
}
